package com.docmgmt.mvp.ragflow;

import com.docmgmt.mvp.ragflow.dto.ParserConfigDTO;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;

/**
 * RAGFlow 知识库创建请求 DTO
 *
 * 用于调用 RAGFlow 的 POST /api/v1/datasets 接口
 *
 * 使用示例：
 * <pre>
 * CreateKnowledgeBaseRequest request = CreateKnowledgeBaseRequest.builder()
 *     .name("技术文档库")
 *     .description("存储技术文档和API文档")
 *     .permission("team")
 *     .chunkMethod("naive")
 *     .embeddingModel("BAAI/bge-large-zh-v1.5")
 *     .build();
 * </pre>
 *
 * @author Dora
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)  // 只包含非null字段
public class CreateKnowledgeBaseRequest {

    /**
     * 知识库名称（必填）
     *
     * 用于标识和区分不同的知识库。
     *
     * 限制：
     * - 不能为空或纯空格
     * - 长度范围：1-128 字符
     * - 同一租户下不能重名
     *
     * 命名建议：
     * - 使用描述性名称，便于识别
     * - 包含知识库的主题或用途
     *
     * 示例：
     * - "技术文档库"
     * - "产品需求文档"
     * - "客户服务知识库"
     */
    @NotBlank(message = "知识库名称不能为空")
    @Size(min = 1, max = 128, message = "知识库名称长度必须在 1-128 字符之间")
    private String name;

    /**
     * 知识库描述（可选）
     *
     * 详细描述知识库的内容和用途。
     *
     * 限制：
     * - 最大长度：65535 字符
     * - 支持多行文本
     *
     * 建议：
     * - 描述知识库包含的文档类型
     * - 说明知识库的使用场景
     * - 列出主要的文档来源
     */
    @Size(max = 65535, message = "描述长度不能超过 65535 字符")
    private String description;

    /**
     * 语言（可选）
     *
     * 指定知识库的主要语言，影响分词和检索效果。
     *
     * 可选值：
     * - Chinese：中文
     * - English：英文
     *
     * 默认值：根据系统语言自动选择
     *
     * 注意：
     * - 此字段主要影响分词策略
     * - 不影响文档的实际语言
     * - 混合语言文档建议选择主要语言
     */
    private String language;

    /**
     * 嵌入模型（可选）
     *
     * 指定用于文档向量化的 embedding 模型。
     *
     * 格式：<model_name>@<provider>
     *
     * 示例：
     * - "BAAI/bge-large-zh-v1.5"（中文推荐）
     * - "BAAI/bge-base-en-v1.5"（英文推荐）
     * - "maidalun1020/bce-embedding-base_v1"
     * - "netease-youdao/bce-embedding-base_v1@SILICONFLOW"
     *
     * 默认值：使用租户的默认 embedding 模型
     *
     * 重要提示：
     * - 创建后不可修改（影响向量一致性）
     * - 同一 Chat Assistant 关联的所有知识库必须使用相同的 embedding 模型
     * - 不同模型的向量不可比较
     */
    @JsonProperty("embedding_model")
    private String embeddingModel;

    /**
     * 权限（可选）
     *
     * 控制知识库的访问权限。
     *
     * 可选值：
     * - me：仅创建者可访问（私有）
     * - team：团队成员可访问（共享）
     *
     * 默认值：me
     *
     * 权限说明：
     * - me：只有创建者可以查看、编辑、删除知识库
     * - team：团队内所有成员可以查看和使用知识库，但只有创建者可以编辑和删除
     *
     * 注意：
     * - 创建后可以修改权限
     * - 修改为 team 后，团队成员立即可见
     */
    @Pattern(regexp = "^(me|team)$", message = "permission 必须是 me 或 team")
    private String permission;

    /**
     * 分块方法（可选）
     *
     * 指定文档的分块策略，影响检索效果和答案质量。
     *
     * 可选值（13种）：
     * - naive：简单分块（默认，适合大多数场景）
     * - manual：手动分块（用户自定义分块规则）
     * - qa：问答对（适合FAQ文档）
     * - table：表格（适合Excel、CSV文件）
     * - paper：学术论文（保留章节结构）
     * - book：书籍（保留章节和目录）
     * - laws：法律文档（保留条款结构）
     * - presentation：演示文稿（按幻灯片分块）
     * - picture：图片（OCR + 分块）
     * - one：单文档（整个文档作为一个chunk）
     * - knowledge_graph：知识图谱（提取实体和关系）
     * - email：邮件（保留邮件结构）
     * - tag：标签（基于标签分块）
     *
     * 默认值：naive
     *
     * 选择建议：
     * - 通用文档：naive
     * - 结构化文档：根据文档类型选择对应方法
     * - 不确定时：使用 naive，后续可以修改
     *
     * 注意：
     * - 创建后可以修改
     * - 修改后需要重新解析文档
     */
    @JsonProperty("chunk_method")
    @Pattern(
        regexp = "^(naive|manual|qa|table|paper|book|laws|presentation|picture|one|knowledge_graph|email|tag)$",
        message = "chunk_method 必须是支持的类型之一"
    )
    private String chunkMethod;

    /**
     * 解析器配置（可选）
     *
     * 针对不同分块方法的详细配置参数。
     *
     * 配置项因 chunk_method 而异，常见配置：
     * - chunk_token_num：每个 chunk 的 token 数量（默认 128）
     * - layout_recognize：布局识别方法（DeepDOC/OCR）
     * - delimiter：分隔符（manual 方法使用）
     * - html4excel：是否将 Excel 转为 HTML（table 方法）
     *
     * 示例：
     * <pre>
     * ParserConfigDTO config = ParserConfigDTO.builder()
     *     .chunkTokenNum(256)
     *     .layoutRecognize("DeepDOC")
     *     .build();
     * </pre>
     *
     * 默认值：根据 chunk_method 自动选择
     *
     * 注意：
     * - 如果不传，使用 RAGFlow 的默认配置
     * - 创建后可以修改
     */
    @JsonProperty("parser_config")
    @Valid
    private ParserConfigDTO parserConfig;

    // ==================== 辅助方法 ====================

    /**
     * 获取权限（非空安全）
     *
     * 如果 permission 为 null，返回默认值 "me"
     *
     * @return 权限
     */
    public String getPermissionOrDefault() {
        return permission != null ? permission : "me";
    }

    /**
     * 获取分块方法（非空安全）
     *
     * 如果 chunkMethod 为 null，返回默认值 "naive"
     *
     * @return 分块方法
     */
    public String getChunkMethodOrDefault() {
        return chunkMethod != null ? chunkMethod : "naive";
    }

    /**
     * 判断是否为团队共享
     *
     * @return 是否为团队共享
     */
    public boolean isTeamShared() {
        return "team".equals(permission);
    }

    /**
     * 判断是否为私有
     *
     * @return 是否为私有
     */
    public boolean isPrivate() {
        return "me".equals(permission) || permission == null;
    }
}
